package br.com.imob.dao;

import br.com.imob.util.HibernateUtil;

import java.io.Serializable;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;

/**
 * @author Gilton Nascimento
 * @version 1.0
 */
public class GenericDao {

    private Session ses;
    private boolean sessionClosed;

    public GenericDao() {
        setSes(getSession());
    }

    public static Session getSession() {
        return HibernateUtil.getInstance().getSession();
    }

    /* Save and Update */
    public void saveOrUpdatePojo(Object obj) {
        getSes().saveOrUpdate(obj);
        safeCommitONClose();
    }
    
    public void savePojo(Object obj) {
    	getSes().saveOrUpdate(obj);
    	safeCommitONClose();
    }
    
    public void updatePojo(Object obj) {
    	getSes().update(obj);
    	safeCommitONClose();
    }
    
    public void updatePojo(Class<Serializable> obj) {
    	getSes().merge(obj);
    	safeCommitONClose();
    }

    public void removerPojo(Object obj) {
        getSes().delete(obj);
        safeCommitONClose();
    }

//    Consultas
    @SuppressWarnings("unchecked")
    public <T extends Serializable> T getPojoByID(Class<T> classe, Serializable key) {
        Serializable obj = (Serializable) getSes().get(classe, key);
        
        if( isSessionClosed() ) sessionClosed();

        return (T) obj;
    }

    @SuppressWarnings("unchecked")
    public <T extends Serializable> T getPojoByQry(String query, Object... params) {
        Query qry = getSes().createQuery(query);

        for (int i = 0; i < params.length; i++) { 
            qry.setParameter(i, params[i]);
        }
        Object obj = qry.uniqueResult();
        sessionClosed();
        return (T) obj;
    }

    @SuppressWarnings("unchecked")
    public <T extends Serializable> T getPojoByQNamed(String qNamed, Object objFiltro) {
        String strParam = qNamed.substring(qNamed.indexOf("By") + 2).toLowerCase();
        Query query = getSes().getNamedQuery(qNamed).setParameter(strParam, objFiltro);
        Object obj = query.uniqueResult();

        if( isSessionClosed() ) { sessionClosed(); }

        return (T) obj;
    }

    /**
     * Fecha a sessão caso seja true e recupera todas as ocorrências daquela tabela
     * @param <T>
     * @param classe Class<T>
     * @return List<T>
     */
    @SuppressWarnings("unchecked")
    public <T extends Object> List<T> getALL(Class<T> classe) {
    	
    	if ( isSessionClosed() ) getSession();
    	
        Query query = getSes().createQuery("SELECT c FROM " + classe.getSimpleName() + " c");
        List<T> itens = query.list();

        if( isSessionClosed() ) { sessionClosed(); }
        
        return itens;
    }


// Ate o momento, eh considerado desnecessario.
    @SuppressWarnings("unchecked")
    public <T extends Serializable> List<T> getListByQNamed(String qryNamed, Object objFiltro) {
        String strParam = qryNamed.substring(qryNamed.indexOf("By") + 2).toLowerCase();

        Query query = getSes().getNamedQuery(qryNamed).setParameter(strParam, objFiltro);
        List<T> itens = query.list();
        sessionClosed();
        return itens;
    }

    @SuppressWarnings("unchecked")
    public <T extends Serializable> List<T> getListByQNamedPRX(String qryNamed, Object objFiltro) {
        String strParam = qryNamed.substring(qryNamed.indexOf("By") + 2).toLowerCase();
        Query query = getSes().getNamedQuery(qryNamed).setParameter(strParam, "%" + objFiltro + "%");
        List<T> itens = query.list();
        sessionClosed();
        return itens;
    }

    @SuppressWarnings("unchecked")
    public <T extends Serializable> List<T> getListByQry( String query, Object... params ) {
    	
    	
    	if( isSessionClosed() ) getSession();
    	
        Query qry = getSes().createQuery(query);
        for (int i = 0; i < params.length; i++)
            qry.setParameter(i, params[i]);
        
        List<T> itens = qry.list();
        sessionClosed();
        return itens;
    }

//  Commits
    private void safeCommitONClose() {
        try {
            getSes().getTransaction().commit();
        } catch (HibernateException e) {
            System.err.println("HibernateException!!\n"
                    + "Error no SafeCommit: " + e.getMessage());
            getSes().getTransaction().rollback();
        }catch (Exception e) {
        	System.err.println("Error no SafeCommit: " + e.getMessage());
        	getSes().getTransaction().rollback();
        } finally { sessionClosed(); }
        
    }
//  CloseSession
    public void sessionClosed() {
        getSes().flush();
        getSes().clear();
        getSes().close();
    }

    /**
     * @return the sessionClosed
     */
    public boolean isSessionClosed() { return sessionClosed; }

    /**
     * @param sessionClosed the sessionClosed to set
     */
    public void setSessionClosed(boolean sessionClosed) { this.sessionClosed = sessionClosed; }
    
    
    public void setSes(Session ses) { this.ses = ses; }
	public Session getSes() { return ses; }	
}